package io.github.luons.mediator.generator;

import io.github.luons.docs.DocsConfig;
import io.github.luons.docs.DocsContext;
import io.github.luons.docs.doc.HtmlDocGenerator;
import io.github.luons.docs.node.ControllerNode;
import io.github.luons.docs.node.RequestNode;
import io.github.luons.mediator.generator.entity.ParamConfig;
import io.github.luons.mediator.generator.entity.ParamNodeBean;
import io.github.luons.mediator.generator.entity.YmlConstant;
import io.github.luons.mediator.generator.model.CommonYml;
import io.github.luons.mediator.generator.model.RequestYml;
import io.github.luons.mediator.generator.utils.YmlUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.util.*;

/**
 * ApiGenerator
 *
 * @author : luons
 */
@Slf4j
public class ApiGenerator {

    /**
     * @param module   生成 module 名称
     * @param version  生成 API 版本
     * @param hostname 生成 API 调用的Host地址
     * @param filepath 生成文件路径
     */
    public static void initConfig(String module, String version, String hostname, String filepath) {
        if (StringUtils.isNotBlank(module)) {
            ParamConfig.MODULE = module;
        }
        if (StringUtils.isNotBlank(version)) {
            ParamConfig.VERSION = version;
        }
        if (StringUtils.isNotBlank(hostname)) {
            ParamConfig.HOST = hostname;
        }
        if (StringUtils.isNotBlank(filepath)) {
            ParamConfig.PATH = filepath;
        }
    }

    /**
     * 生成所有接口 OpenApi
     *
     * @param config DocsConfig
     * @return boolean
     */
    public static void ymlService(DocsConfig config) {
        ymlService(null, config);
    }

    /**
     * 生成固定controller OpenApi
     *
     * @param controllers controller名列表
     * @param config      DocsConfig
     * @return boolean
     */
    public static void ymlService(final List<String> controllers, DocsConfig config) {

        DocsContext.init(config);
        HtmlDocGenerator docGenerator = new HtmlDocGenerator();
        List<ControllerNode> controllerNodes = docGenerator.getControllerNodeList();
        if (CollectionUtils.isEmpty(controllerNodes)) {
            log.warn("scan Controller is blank!");
            return;
        }
        String basePath = DocsContext.getDocPath() + File.separator + ParamConfig.PATH + File.separator;
        String filePath = basePath + ParamConfig.VERSION + File.separator;

        for (ControllerNode controllerNode : controllerNodes) {
            LinkedHashMap<String, Object> ymlMap = new LinkedHashMap<>();
            LinkedHashMap<String, Map<String, Object>> pathMap = new LinkedHashMap<>();
            if (CollectionUtils.isNotEmpty(controllers) && !controllers.contains(controllerNode.getClassName())) {
                continue;
            }
            List<RequestNode> list = controllerNode.getRequestNodes();
            if (CollectionUtils.isEmpty(list)) {
                continue;
            }
            YmlUtils.URL_PARAM_MAP = new HashMap<>();
            for (RequestNode requestNode : list) {
                // 统一生成在Service 层下
                Map<String, Object> requestMap = RequestYml.genMethodRequest(filePath, requestNode);
                String url = requestNode.getUrl().trim().replaceAll("/v\\d+/", "/");
                if (!pathMap.containsKey(url)) {
                    pathMap.put(url, requestMap);
                } else {
                    pathMap.get(url).putAll(requestMap);
                }
            }
            // 生成YML文件
            ymlMap.put("swagger", YmlConstant.SWAGGER_VERSION);
            LinkedHashMap<String, Object> info = new LinkedHashMap<>();
            ymlMap.put("info", info);
            info.put("title", controllerNode.getClassName());
            info.put("version", ParamConfig.VERSION);
            info.put("description", controllerNode.getDescription());
            ymlMap.put("paths", pathMap);

            if (MapUtils.isNotEmpty(YmlUtils.URL_PARAM_MAP)) {
                Map<String, Object> paramsMap = new LinkedHashMap<>();
                for (Map.Entry<String, ParamNodeBean> entry : YmlUtils.URL_PARAM_MAP.entrySet()) {
                    if (Objects.isNull(entry.getValue())) {
                        continue;
                    }
                    ParamNodeBean pn = entry.getValue();
                    Map<String, Object> data = new LinkedHashMap<>();
                    data.put("name", entry.getKey());
                    data.put("in", "path");
                    data.put("required", true);
                    data.put("type", StringUtils.isBlank(pn.getType()) ? "string" : pn.getType());
                    data.put("description", StringUtils.isBlank(pn.getDescription()) ? "" : pn.getDescription());
                    paramsMap.put(entry.getKey(), data);
                }
                ymlMap.put("parameters", paramsMap);
            }
            YmlUtils.ymlGenerator((filePath + "/service/"), controllerNode.getClassName() + ".yaml", ymlMap);
        }

        // 生成summary.yaml、Error.yaml文件
        YmlUtils.ymlGenerator(filePath, "summary.yaml", CommonYml.ymlSummary());
        YmlUtils.ymlGenerator((basePath + ParamConfig.MODULE + "/"), "summary.yaml", CommonYml.ymlSummary());
        YmlUtils.ymlGenerator((filePath + "/model/"), "Error.yaml", CommonYml.ymlError());
    }

}
